home *** CD-ROM | disk | FTP | other *** search
- # include "nrs.h"
-
- # ifndef lint
- static char RCSid[]="@(#)$Header: lru.c,v 3.1 86/10/15 08:13:18 pb Rel $";
- # endif
-
- /***********************************************************************\
- * *
- * get a file descriptor. As there are up to 39+ files in use, these *
- * are kept in an lru queue to keep i/o efficient. *
- * These routines are based heavily on those Dave Allsopp wrote *
- * for a compiler, Thanks Dave. *
- * *
- * Copyright 1986, Piete Brooks, Julian Onions & Adrian Pell *
- * pb@cl.cam.ac.uk, jpo@hcig.nott.ac.uk, Adrian.R.Pell@reading.ac.uk *
- * *
- * This program may be copied as long as you don't remove this notice, *
- * try to make any money off of it, or pretend that you wrote it. *
- * *
- \***********************************************************************/
-
- # define NILLIST ((Flist *)0)
- # define MAXOPENFILES 10 /* max files kept in lru queue */
- # define MAXFILES 64 /* max files kept in table */
-
- typedef struct flist { /* the lru queue unit */
- FILE *fp;
- int tab_no;
- struct flist *next;
- } Flist;
-
- typedef struct Files {
- char *filename;
- int used;
- } Files;
-
- static Files FileList[MAXFILES];
- static Flist *Head = NILLIST; /* the head of the lru list */
- static_f Flist *search_list();
- static_f int getfileindex();
- static_f void tohead();
- static_f Flist *get_newfl();
-
- FILE *getfp(name, mode) /* find fp for name opening if necessary */
- char *name;
- char *mode;
- {
- Flist *flp;
- int n;
-
- n = getfileindex(name);
- if((flp = search_list(n, Head)) == NILLIST)
- flp = get_newfl(n, &Head, mode);
-
- if (flp == NILLIST) return (FILE *) 0;
-
- tohead(n, &Head); /* shift to head of queue */
- return flp->fp;
- }
-
- static_f
- Flist *
- search_list(n, start)
- int n;
- Flist *start;
- {
- register Flist **tracer;
-
- for(tracer = &start; *tracer != NILLIST && (*tracer)->tab_no != n;
- tracer = &(*tracer)->next)
- ;
- return *tracer;
- }
-
- static_f Flist *get_newfl(n, start, mode) /* open the file */
- int n;
- Flist **start;
- char *mode;
- {
- register Flist **tracer = start;
- register int i;
- char newmode[4];
- int soft_fail = *mode == 'S';
-
- if (soft_fail) mode++;
-
- #ifdef PRIME
- if (*mode == 'r')
- VOID strcpy(newmode, "i");
- else if (*mode == 'w' && FileList[n].used) /* convert to an append */
- VOID strcpy(newmode, "oa+");
- else
- VOID strcpy(newmode, "o+");
- #else PRIME
- if( *mode == 'w' && FileList[n].used) /* convert to an append */
- newmode[0] = 'a';
- else newmode[0] = *mode;
- newmode[1] = mode[1];
- newmode[2] = '\0';
- #endif PRIME
-
- if( *tracer == NILLIST) /* nothing in the queue, make an entry */
- {
- *tracer = (Flist *)malloc((unsigned) sizeof(Flist));
- if( *tracer == NILLIST)
- fatal0("Out of memory in lru");
- (*tracer)->next = NILLIST;
- }
- else
- {
- for( i = 1; (*tracer)->next != NILLIST; i++)
- tracer = &(*tracer)->next;
- if( i == MAXOPENFILES) /* time to shut one down */
- VOID fclose((*tracer)->fp);
- else /* room for a small one ? */
- {
- tracer = &(*tracer)->next;
- *tracer = (Flist *)malloc((unsigned) sizeof(Flist));
- if( *tracer == NILLIST)
- fatal0("Out of memory");
- (*tracer)->next = NILLIST;
- }
- }
- if(((*tracer)->fp = fopen(FileList[n].filename, newmode)) == NULL)
- { if (soft_fail)
- { Flist *next = (*tracer)->next;
- free((char *) (*tracer));
- *tracer = next;
- return NILLIST;
- }
- fatal1("Can't open file %s", FileList[n].filename);
- }
- FileList[n].used = 1;
- (*tracer)->tab_no = n;
- return *tracer;
- }
-
- static_f void
- tohead(n, start) /* move node n to head of list */
- int n;
- Flist **start;
- {
- register Flist **tracer = start;
- register Flist *tmp;
-
- while(*tracer != NILLIST && (*tracer)->tab_no != n)
- tracer = &(*tracer)->next;
- if( *tracer == NILLIST)
- fatal1("lru botch looking for %d", n);
- tmp = *tracer;
- *tracer = tmp->next;
- tmp->next = *start;
- *start = tmp;
- }
-
- static_f int
- getfileindex(name)
- char *name;
- {
- Files *fsp;
-
- for(fsp = FileList; fsp->filename != NULL; fsp++)
- if( strcmp(fsp->filename, name) == 0)
- return fsp - FileList;
- /* make a new entry */
- if( fsp - FileList > MAXFILES )
- fatal0("Too many files to deal with - help");
- fsp->filename = strdup(name);
- fsp->used = 0;
- return fsp - FileList;
- }
-